package  org.sissgr.utilidades{
	
	import flash.errors.IllegalOperationError;
	import flash.utils.Dictionary;
	
	/**
	 * Provides a simple way to access objects references from anywhere by using id(s)
	 * 
	 * @author Davide Zanotti (davidezanotti@gmail.com)
	 * 
	 * @example 
	 * 
	 * // From anywhere you first create and register objects:<br /><br />
	 * 
	 * var collector:ObjectCollector = ObjectCollector.getInstance();<br />
	 * var myObj1:Button = new Button();<br /><br />
	 * 
	 * myObj1.width = 300;<br />
	 * myObj1.label = "my first button";<br />
	 * myObj1.id = "myFirstButton"; // id is mandatory, otherwise you'll get an error<br /><br />
	 * 
	 * var myObj2:TextInput = new TextInput();<br />
	 * myObj2.text = "hello world";<br />
	 * myObj2.id = "myTextField"; // id is mandatory, otherwise you'll get an error<br /><br />
	 * 
	 * collector.registerObject(myObj1);<br />
	 * collector.registerObject(myObj2);<br /><br />
	 * 
	 * // ...then in another (or the same) place you can get references to your desired objects.<br />
	 * // (this time by specifying the id)<br />
	 * // When you retrieve objects from the collector you should always cast (upcast!) them to the right type<br />
	 * // (Because objects are collected as generic Object classes)<br /><br />
	 * 
	 * var btn:Button = Button(ObjectCollector.getInstance().getObject("myFirstButton"));<br /><br />
	 * 
	 * // When/if you don't need these reference anymore, you can remove them by id:<br /><br />
	 * 
	 * ObjectCollector.getInstance().unregisterObject("myFirstButton");<br /><br />
	 * 
	 * // or all together:<br /><br />
	 * 
	 * ObjectCollector.getInstance().unregisterAll();
	 * 
	 */
	public final class ObjectCollector {
		
		private static var _instance:ObjectCollector = new ObjectCollector();
		private var _dictionary:Dictionary;
		
		/**
		 * ObjectCollector's constructor function
		 * 
		 * @throw IllegalOperationError <span>This class is a Singleton, this error is throw when 
		 * you attempt to use the constructor instead of getInstance() method</span>
		 */
		public function ObjectCollector() {
			
			if (_instance != null) {
				
				throw new IllegalOperationError("Unable to create an instance of ObjectCollector using it's constructor. You must use getInstance() method");
				
			}
			
			this._dictionary = new Dictionary();
			
		}
		
		/**
		 * Returns the current ObjectCollector's instance
		 * 
		 * @return ObjectCollector <span>ObjectCollector's instance</span>
		 */
		public static function getInstance():ObjectCollector {
			
			return _instance;
			
		}
		
		/**
		 * Returns a reference to an object registered with the specified id
		 * 
		 * @param id <span>String used as object identifier</span>
		 * 
		 * @return Object <span>Object registered</span>
		 */
		public function getObject(id:String):Object {
			
			if (!this._dictionary.hasOwnProperty(id)) {
				
				throw new Error('No object registerd with id "' + id + '"');
				
			}
			
			return this._dictionary[id];
			
		}
		
		/**
		 * Returns all references to registered objects
		 * 
		 * @return Array <span>A (heterogeneous) collection of references to registered objects</span>
		 */
		public function getAll():Array {
			
			var objects:Array = [];
			
			for each (var i:Object in this._dictionary) {
				
				objects.push(this._dictionary[i]);
				
			}
			
			return objects;
			
		}
		
		/**
		 * Adds an object's reference to ObjectCollector's collection
		 * 
		 * @param obj <span>Any type of Object you need to get a reference to</span>
		 */
		public function registerObject(obj:Object):void {
			
			if (!obj.hasOwnProperty("id") || obj.id == null || obj.id == "") {
				
				throw new Error("You have to specify an ID for the object you want to register!");
				
			}
			
			// Adds object to the Dictionary
			this._dictionary[obj.id] = obj;
			
		}
		
		
		/**
		 * Removes a reference to a previously registered object (specified by id)
		 * 
		 * @param id <span>String used as object identifier</span>
		 * 
		 * @return Boolean <span>True if the reference has been found and removed
		 * from ObjectCollector's collection, false otherwise (the reference with 
		 * the specified id was never been registered)</span>
		 */
		public function unregisterObject(id:String):Boolean {
			
			if (this._dictionary.hasOwnProperty(id)) {
				
				// Removes registered object
				delete this._dictionary[id];
				
				return true;
				
			}
			
			return false;
			
		}
		
		/**
		 * Removes all the references to registerd objects
		 */
		public function unregisterAll():void {
			
			// Reinitializes the internal Dictionary
			this._dictionary = new Dictionary();
			
		}
		
	}
	
}